package com.onpositive.knowledge.model.values;

import com.onpositive.data.IPropertyConstants;
import com.onpositive.knowledge.model.IHasUniverse;
import com.onpositive.knowledge.model.IHasVersions;
import com.onpositive.knowledge.model.IThing;
import com.onpositive.knowledge.model.IUniverse;
import com.onpositive.knowledge.model.impl.BasicUniverseProperty;
import com.onpositive.knowledge.model.impl.PropertyTypeImpl;
import com.onpositive.semantic.model.api.changes.ObjectChangeManager;
import com.onpositive.semantic.model.api.labels.ILabelLookup;
import com.onpositive.semantic.model.api.labels.NotFoundException;
import com.onpositive.semantic.model.api.meta.DefaultMetaKeys;
import com.onpositive.semantic.model.api.property.IProperty;
import com.onpositive.semantic.model.api.property.PropertyAccess;
import com.onpositive.semantic.model.api.property.java.annotations.RealmProvider;
import com.onpositive.semantic.model.ui.generic.IKnowsImageObject;

public class PropertyValuePair implements IKnowsImageObject{

	public final IProperty property;
	public final Object target;
	public final Object comment;
	
	public PropertyValuePair(IProperty property, IHasValue value,Object tg, Object comment) {
		super();
		this.property = property;
		this.value = value;
		this.target=tg;
		this.comment = comment;
	}
	public IHasValue value;
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((property == null) ? 0 : property.hashCode());
		result = prime * result + ((value == null) ? 0 : value.hashCode());
		result = prime * result + ((target == null) ? 0 : target.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		PropertyValuePair other = (PropertyValuePair) obj;
		if (property == null) {
			if (other.property != null)
				return false;
		} else if (!property.equals(other.property))
			return false;
		if (value == null) {
			if (other.value != null)
				return false;
		} else if (!value.equals(other.value))
			return false;
		if (target == null) {
			if (other.target != null)
				return false;
		} else if (!target.equals(other.target))
			return false;
		return true;
	}
	
	public String getId(){
		if(target instanceof IThing){
			IThing th = (IThing) target;
			return th.getId();
		}
		return property.getId();
	}
	
	public String getPropertyId(){		
		return property.getId();
	}
	
	@RealmProvider(value=MPProvider.class)
	public Object getValue(){
		if (value==null){
			return null;
		}
		Object value2 = value.value();
		return value2;
	}
	
	public void setValue(Object object){
		ILabelLookup service = DefaultMetaKeys.getService(property, ILabelLookup.class);
		try {
			Object lookUpByLabel = service.lookUpByLabel(property, target, object.toString());
			Object vl=value!=null? value.value():null;
			if (lookUpByLabel!=null&&!lookUpByLabel.equals(vl)){
				PropertyAccess.setValue(property, target, lookUpByLabel);
			}
			else if (lookUpByLabel==null&&value!=null){
				PropertyAccess.setValue(property, target, lookUpByLabel);
			}
			value=(DescribedValue) property.getValue(target);
		} catch (NotFoundException e) {
			
		}
		ObjectChangeManager.markChanged(this);
	}
	
	public PropertyTypeImpl  getType(){
		if (property instanceof BasicUniverseProperty){
			BasicUniverseProperty bp=(BasicUniverseProperty) property;
			return bp.getType();
		}
		return null;		
	}
	
	public boolean isDepricated(){
		return DefaultMetaKeys.getValue(property, IPropertyConstants.CHAR_DEPRICATED_LABEL, Boolean.class, false);
	}
	
	@Override
	public String toString() {
		return getId();
	}
	
	public void contributeStandardComplete() {
		
		IHasVersions ihv = extractDestination();
		if( ihv != null )
			ihv.contributeStandard( (IThing)this.target, null ) ;		
	}
	
	public void contributeStandard() {
		IHasVersions ihv = extractDestination();
		if( ihv != null )
			ihv.contributeStandard( (IThing)this.target, this.property ) ;		
	}
	
	public IHasVersions extractDestination() {
		if( !(this.target instanceof IHasUniverse) )
			return null;
		
		if( !(this.target instanceof IThing) )
			return null;
		
		IHasUniverse th = (IHasUniverse) target ;
		IUniverse universe = th.getUniverse() ;
		
		if( !(universe instanceof IHasVersions) )
			return null;
		
		IHasVersions ihv = (IHasVersions) universe ;
		return ihv;
	}
	public Object getTarget() {
		return target;
	}
	@Override
	public String getImageID() {
		if(target instanceof IKnowsImageObject)
			return ((IKnowsImageObject)target).getImageID() ;
		
		return null;
	}
	public Object getComment() {
		return comment;
	}
	
}
